package com.xyrl.project.common.store.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyrl.common.util.ObjectUtil;
import com.xyrl.project.common.common.entity.AttachmentImageUse;
import com.xyrl.project.common.common.enu.AttImageUseType;
import com.xyrl.project.common.common.service.AttachmentImageUseService;
import com.xyrl.project.common.common.service.AttachmentService;
import com.xyrl.project.common.common.vo.AttachmentVo;
import com.xyrl.project.common.store.dao.StoreAuthLogMapper;
import com.xyrl.project.common.store.dao.StoreAuthMapper;
import com.xyrl.project.common.store.entity.*;
import com.xyrl.project.common.store.enu.StoreAuthStatus;
import com.xyrl.project.common.store.enu.StoreAuthType;
import com.xyrl.project.common.store.enu.StoreStatus;
import com.xyrl.project.common.store.enu.StoreStatusNode;
import com.xyrl.project.common.store.service.StoreAuthService;
import com.xyrl.project.common.store.service.StoreImageService;
import com.xyrl.project.common.store.service.StoreLegalService;
import com.xyrl.project.common.store.service.StoreService;
import com.xyrl.project.common.store.vo.StoreAuthVo;
import com.xyrl.project.common.util.ListUtil;
import com.xyrl.project.common.util.ReflectionUtils;
import com.xyrl.starter.lock.redis.annotations.LockAction;
import com.xyrl.third.baidu.service.PersonVerifyService;
import com.xyrl.third.baidu.vo.BaiduPersonVerifyVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.EnumUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;


/**
* @className StoreAuthServiceImpl.java
* @company 重庆星纭融链科技公司
* @author 徐恩源
* @version 1.0
* @date 2019-12-27 11:25:42
* @Description 用户认证表serviceImpl
*/
@Slf4j
@Service
public class StoreAuthServiceImpl extends ServiceImpl<StoreAuthMapper, StoreAuth> implements StoreAuthService {
    @Autowired
    private StoreService storeService;
    @Autowired
    private PersonVerifyService personVerifyService;
    @Autowired
    private StoreLegalService storeLegalService;
    @Autowired
    private StoreAuthLogMapper storeAuthLogMapper;
    @Autowired
    private StoreImageService storeImageService;
    @Autowired
    private AttachmentService attachmentService;


    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    @LockAction(group = "locks:faceAuth:", value = "#storeId")
    public String faceAuth(Long storeId, Long salesId, List<Long> attIds, boolean isSalesUser) {
        Store store = null;
        if (isSalesUser) {
            store = storeService.checkOpStorePermission(storeId, salesId);
        } else {
            store = storeService.findById(storeId);
        }

        if (!StoreStatusNode.idCard.equals(store.getStatusNote())) {
            return "认证失败,请先提交身份证信息";
        }
        List<AttachmentVo> attVoList = attachmentService.findListByIdList(attIds);
        if (ObjectUtil.isEmpty(attIds) || attVoList.size() != attIds.size()) {
            return "认证失败，未找到认证图片";
        }
        // 保存身份证信息
        StoreLegal storeLegal = storeLegalService.findStoreLegalByStoreId(store.getId());
        log.debug("开始调用实名认证,认证头像:{}", attVoList.get(0).getShowUrl());
        //身份认证(调用百度身份认证 与公安中的身份证照片进行核对）
        BaiduPersonVerifyVo verifyInfo = personVerifyService.urlPersonVerify(attVoList.get(0).getShowUrl(), storeLegal.getRealName(), storeLegal.getIdCard());
        //根据比对分值进行判断身份认证是否成功
        if (ObjectUtil.isEmpty(verifyInfo)||ObjectUtil.isEmpty(verifyInfo.getResult()) || ObjectUtil.isEmpty(verifyInfo.getResult().getScore())
                || verifyInfo.getResult().getScore().doubleValue() < 80) {
            return "实名认证未通过";
        }
        Store mStore = new Store();
        mStore.setId(storeId);
        mStore.setStatusNote(StoreStatusNode.face);
        mStore.setStatus(StoreStatus.wait);
        storeService.updateById(mStore);
        // 修改认证信息
        this.updateStoreAuth(store.getId(), salesId, StoreAuthType.realNameAuth, StoreAuthStatus.YES);
        // 处理附件信息
        List<Long> oldAttIdList = storeImageService.getAttIdList(storeId, StoreAuthType.realNameAuth);
        attachmentService.handleAttImageUseAttId(storeId, AttImageUseType.faceAuth, attIds, oldAttIdList);
        return null;
    }


    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public void updateStoreAuth(long storeId, Long salesId, StoreAuthType storeAuthType, StoreAuthStatus storeAuthStatus) {
        // 修改认证信息
        StoreAuth storeAuth = new StoreAuth();
        Field field = ReflectionUtils.getAccessibleField(StoreAuth.class, storeAuthType.name());
        Assert.notNull(field, "认证失败，未找到认证实体");
        ReflectionUtils.setFieldValue(storeAuth, storeAuthType.name(), storeAuthStatus);
        storeAuth.setId(storeId);
        super.updateById(storeAuth);
        // 保存认证记录
        StoreAuthLog storeAuthLog = new StoreAuthLog();
        storeAuthLog.setStoreId(storeId);
        storeAuthLog.setAuthType(storeAuthType);
        storeAuthLog.setStatus(storeAuthStatus);
        storeAuthLog.setSalesId(salesId);
        storeAuthLog.setCreateTime(new Date());
        storeAuthLogMapper.insert(storeAuthLog);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStoreAuth(long storeId, long salesId, StoreAuthType storeAuthType, Long[] attIds) {
        StoreAuthStatus authStatus = ObjectUtil.isNotEmpty(attIds) ? StoreAuthStatus.YES : StoreAuthStatus.NO;
        this.updateStoreAuth(storeId, salesId, storeAuthType, authStatus);
        // 新数据
        List<Long> newAttIdList = new ArrayList<>(Arrays.asList(attIds));
        // 旧数据
        List<Long> oldAttIdList = storeImageService.getAttIdList(storeId, storeAuthType);
        //新增数据项
        List<Long> addAttIdList = ListUtil.getAddaListThanbList(newAttIdList, oldAttIdList);
        // 删除数据项
        List<Long> delAttIdList = ListUtil.getReduceaListThanbList(newAttIdList, oldAttIdList);

        //添加图片
        saveStoreImage(addAttIdList, storeId, storeAuthType, "");
        //删除图片
        deleteStoreImage(delAttIdList, storeId);
        AttImageUseType useType = null;
        if (storeAuthType.equals(StoreAuthType.buyerTradeRecord)) {
            useType = AttImageUseType.buyerTradeRecord;
        } else {
            useType = AttImageUseType.sellerPic;
        }
        attachmentService.handleAttImageUseAttId(storeId, useType, addAttIdList, delAttIdList);
    }
    /**
     * 删除门店图片
     * @author 徐恩源
     * @date 2020-01-06 16:14:58
     * @param delAttIdList
     * @param storeId
     */
    private void deleteStoreImage(List<Long> delAttIdList, Long storeId) {
        if (ObjectUtil.isEmpty(delAttIdList)) {
            return;
        }
        LambdaQueryWrapper<StoreImage> imageWrapper = new LambdaQueryWrapper<>();
        imageWrapper.in(StoreImage::getAttId, delAttIdList);
        imageWrapper.eq(StoreImage::getStoreId, storeId);
        storeImageService.remove(imageWrapper);
    }

    /**
     * 保存门店图片
     * @author 徐恩源
     * @date 2020-01-06 11:04:17
     * @param addAttIdList
     * @param storeId
     * @param storeAuthType
     * @param minType
     */
    private void saveStoreImage(List<Long> addAttIdList, long storeId, StoreAuthType storeAuthType, String minType) {
        if (ObjectUtil.isEmpty(addAttIdList)) {
            return;
        }
        List<AttachmentVo> voList = attachmentService.findListByIdList(addAttIdList);
        Assert.notEmpty(voList, "未找到认证照片");
        Assert.isTrue(voList.size() == addAttIdList.size(), "未找到认证照片");
        // 保存图片
        List<StoreImage> storeImageList = new ArrayList<>();
        voList.forEach(vo -> {
            StoreImage storeImage = new StoreImage();
            storeImage.setCreateTime(new Date());
            storeImage.setStoreId(storeId);
            storeImage.setType(storeAuthType.name());
            storeImage.setImageUrl(vo.getPath());
            storeImage.setAttId(vo.getId());
            storeImage.setMinType(minType);
            storeImageList.add(storeImage);
        });
        // 保存附件使用场景
        storeImageService.saveBatch(storeImageList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStoreAuth(long salesId, long storeId, List<StoreImage> list) {
        // 修改图片认证信息
        StoreAuthStatus authStatus = ObjectUtil.isNotEmpty(list) ? StoreAuthStatus.YES : StoreAuthStatus.NO;
        this.updateStoreAuth(storeId, salesId, StoreAuthType.buyerStorePic, authStatus);

        // 图片附件信息
        List<Long> newAttIdList = list.stream().map(StoreImage::getAttId).collect(Collectors.toList());
        // 查询附件id
        List<Long> oldAttIdList = storeImageService.getAttIdList(storeId, StoreAuthType.buyerStorePic);
        // 要添加的
        List<Long> addAttIdList = ListUtil.getAddaListThanbList(newAttIdList, oldAttIdList);
        // 要删除的
        List<Long> delAttIdList = ListUtil.getReduceaListThanbList(newAttIdList, oldAttIdList);

        // 执行添加操作
        saveStoreImage(addAttIdList, list);
        // 执行修改操作
        deleteStoreImage(delAttIdList, storeId);
        // 处理附件
        attachmentService.handleAttImageUseAttId(storeId, AttImageUseType.buyerStorePic, addAttIdList, delAttIdList);
    }

    private void saveStoreImage(List<Long> addAttIdList, List<StoreImage> list) {
        if (ObjectUtil.isEmpty(addAttIdList)) {
            return;
        }
        List<AttachmentVo> attachmentVoList = attachmentService.findListByIdList(addAttIdList);
        Assert.notEmpty(attachmentVoList, "未找到认证照片");
        Assert.isTrue(attachmentVoList.size() == addAttIdList.size(), "未找到认证照片");

        List<StoreImage> addList = new ArrayList<>();
        for (AttachmentVo vo : attachmentVoList) {
            for (StoreImage storeImage : list) {
                if (vo.getId().equals(storeImage.getAttId())) {
                    storeImage.setImageUrl(vo.getPath());
                    addList.add(storeImage);
                    list.remove(storeImage);
                    break;
                }
            }
        }
        storeImageService.saveBatch(addList);
    }

    @Override
    public StoreAuth saveStoreAuth(long storeId) {
        StoreAuth storeAuth = new StoreAuth();
        storeAuth.setId(storeId);
        storeAuth.setRealNameAuth(StoreAuthStatus.NO);
        storeAuth.setLicenseAuth(StoreAuthStatus.NO);
        storeAuth.setBankList(StoreAuthStatus.NO);
        storeAuth.setBuyerTradeRecord(StoreAuthStatus.NO);
        storeAuth.setBuyerStorePic(StoreAuthStatus.NO);
        storeAuth.setBuyerContract(StoreAuthStatus.NO);
        storeAuth.setSellerContract(StoreAuthStatus.NO);
        storeAuth.setSellerPic(StoreAuthStatus.NO);
        int count = baseMapper.insert(storeAuth);
        if (count > 0) {
            return storeAuth;
        }
        return null;
    }

    @Override
    public StoreAuthVo findStoreAuthVoByStoreId(long storeId, long salesId) {
        Store store = storeService.checkStoreBySalesId(storeId, salesId);
        if (null == store) {
            return null;
        }
        StoreAuth storeAuth = this.getById(storeId);
        if (null == storeAuth) {
            storeAuth = this.saveStoreAuth(storeId);
        }
        StoreAuthVo storeAuthVo = new StoreAuthVo();
        BeanUtils.copyProperties(storeAuth, storeAuthVo);
        BeanUtils.copyProperties(store, storeAuthVo);
        storeAuthVo.setBuyerCompleteFlag(false);
        storeAuthVo.setSellerCompleteFlag(false);
        // 基础资料填写（实名认证+营业执照认证）
        boolean basicFlag = StoreAuthStatus.YES.equals(storeAuth.getRealNameAuth())
                || StoreAuthStatus.YES.equals(storeAuth.getLicenseAuth());
        // 进货商资料填写（交易流水+门店照片认证）
        boolean buyerFlag = StoreAuthStatus.YES.equals(storeAuth.getBuyerTradeRecord())
                || StoreAuthStatus.YES.equals(storeAuth.getBuyerStorePic());
        //  供货商资料填写（供货商资质）
        boolean sellerFlag = StoreAuthStatus.YES.equals(storeAuth.getSellerPic());
        // 判断进货商资料是否填写完
        if (basicFlag && buyerFlag) {
            storeAuthVo.setBuyerCompleteFlag(true);
        }
        // 判断供货商资料是否填写完
        if (basicFlag && sellerFlag) {
            storeAuthVo.setSellerCompleteFlag(true);
        }
        // 是否填写身份证信息
        if (StoreStatusNode.idCard.equals(store.getStatusNote())) {
            StoreLegal storeLegal = storeLegalService.findStoreLegalByStoreId(storeId);
            storeAuthVo.setStoreLegal(storeLegal);
        }
        return storeAuthVo;
    }
}
